package co.gov.medellin.ssti.sub.web.action;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import co.gov.medellin.ssti.sub.common.excepcion.SUBException;
import co.gov.medellin.ssti.sub.common.util.CondicionConsultaUtilVO;
import co.gov.medellin.ssti.sub.common.util.FiltrosReportesUtil;
import co.gov.medellin.ssti.sub.common.util.Utility;
import co.gov.medellin.ssti.sub.model.dao.exception.DAOException;
import co.gov.medellin.ssti.sub.model.service.ProgramaService;
import co.gov.medellin.ssti.sub.model.service.ReporteTotalComunaService;
import co.gov.medellin.ssti.sub.model.service.SubprogramaService;
import co.gov.medellin.ssti.sub.model.service.VflexService;
import co.gov.medellin.ssti.sub.model.vo.CondicionConsultaVO;
import co.gov.medellin.ssti.sub.model.vo.ProgramaVO;
import co.gov.medellin.ssti.sub.model.vo.ReportComunaVO;
import co.gov.medellin.ssti.sub.model.vo.ReporteTotalComunaVO;
import co.gov.medellin.ssti.sub.model.vo.SubprogramaVO;
import co.gov.medellin.ssti.sub.model.vo.VflexVO;
import co.gov.medellin.ssti.sub.paoyer.administration.model.vo.UserVO;
import co.gov.medellin.ssti.sub.web.form.ReportTotalComunaForm;

@Component
public class ReportTotalComunaAction extends Action {
	private static final Logger logger = Logger
			.getLogger(ReportTotalComunaAction.class);
	/*
	 * Beans inyectados.
	 */
	@Autowired
	ProgramaService programaServiceImpl;
	@Autowired
	ReporteTotalComunaService reporteTotalComunaServiceImpl;
	@Autowired
	SubprogramaService subprogramaServiceImpl;
	@Autowired
	VflexService vflexServiceImpl;
	@Autowired
	FiltrosReportesUtil filtrosReportesUtil;

	/**
	 * This is the main action called from the Struts framework.
	 * 
	 * @param mapping
	 *            The ActionMapping used to select this instance.
	 * @param form
	 *            The optional ActionForm bean for this request.
	 * @param request
	 *            The HTTP Request we are processing.
	 * @param response
	 *            The HTTP Response we are processing.
	 * @return
	 * @throws java.io.IOException
	 * @throws javax.servlet.ServletException
	 */
	@SuppressWarnings("unchecked")
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {

		HttpSession session = request.getSession();
		UserVO user = (UserVO) session.getAttribute("userInfo");
		session.removeAttribute("msg");
		session.removeAttribute("beneficiosReporteTotalComuna");
		session.removeAttribute("criteriaRepTotComuna");
		session.setAttribute("msg", "");

		// tst
		// String selectedPrograma;
		// session.removeAttribute("Beneficios");

		// se obtiene la form y se asignan los valores
		ReportTotalComunaForm formBean = (ReportTotalComunaForm) form;

		if ((Collection<CondicionConsultaVO>) session
				.getAttribute("filtrosRepTotComuna") != null) {
			formBean.setFiltros((Collection<CondicionConsultaVO>) session
					.getAttribute("filtrosRepTotComuna"));
		}

		request.setAttribute("filtrosRepTotComuna", formBean.getFiltros());

		try {
			// Carga las zonas, comunas, programas.
			Collection<VflexVO> zonas = vflexServiceImpl
					.findVflex(VflexService.ZONA);
			formBean.setZonas(zonas);
			Collection<VflexVO> comunas = vflexServiceImpl
					.findVflex(VflexService.COMUNA);
			formBean.setComunas(comunas);
			Collection<ProgramaVO> programas = programaServiceImpl
					.findProgramaByUserReport(user.getCode(),
							user.getUserGroupName(), user.getCodeArea());
			formBean.setProgramas(programas);
			// Si se hace un refresh y ya tiene seleccionado un programa, carga
			// los subprogramas correspondientes.
			if (formBean.getCodePrograma() != null
					&& formBean.getCodePrograma().length() > 0) {
				Collection<SubprogramaVO> subprogramas = findSubprogramas(user,
						formBean);
				if (subprogramas != null) {
					formBean.setSubprogramas(subprogramas);
				}
			}

		} catch (DAOException e) {
			SUBException.logDebugError("", e);
		}

		// cuando elige una zona. (Se remplazo por un metodo en VisualHelper -
		// dwr.)
		if (formBean.getOperacion().equalsIgnoreCase(Utility.OP_SELECT_ZONA)) {
			String codeZona = formBean.getCodeZona();

			Collection<VflexVO> cComunas;
			// busca las comunas pertenecientes a la zona.
			if (!codeZona.equals("")) {
				cComunas = vflexServiceImpl.findVflex(VflexService.COMUNA,
						codeZona);
			} else {
				cComunas = vflexServiceImpl.findVflex(VflexService.COMUNA);
			}

			formBean.setComunas(cComunas);
		}

		// cuando selecciona una comuna.
		if (formBean.getOperacion().equalsIgnoreCase(Utility.OP_SELECT_COMUNA)) {
			String codeComuna = formBean.getCodeComuna();
			String codeZona = formBean.getCodeZona();
			String zona;

			if (codeZona.equals("")) {
				if (!codeComuna.equals("")) {
					Long codZona = vflexServiceImpl
							.findCodePadreByCodeHijo(new Long(codeComuna));
					zona = (codZona == null ? "" : Long.toString(codZona
							.longValue()));
					formBean.setCodeZona(zona);
					Collection<VflexVO> cComunas = vflexServiceImpl.findVflex(
							"COMUNA", zona);
					formBean.setComunas(cComunas);
				} else {
					Collection<VflexVO> cComunas = vflexServiceImpl
							.findVflex("COMUNA");
					formBean.setComunas(cComunas);
				}
			} else {
				zona = codeZona;
				request.setAttribute("zona", codeZona);
			}
		}

		// Llenar la lista de subprogramas correspondientes cuando ha elegido un
		// programa.. (Se remplazo por un metodo en VisualHelper -
		// dwr.)
		if (formBean.getOperacion()
				.equalsIgnoreCase(Utility.OP_SELECT_PROGRAMA)) {
			if (formBean.getCodePrograma() != null
					&& formBean.getCodePrograma().length() > 0) {
				try {
					Collection<SubprogramaVO> subprogramas = subprogramaServiceImpl
							.findSubprogramaUser(user.getCode(),
									user.getUserGroupName(),
									new Long(formBean.getCodePrograma()),
									user.getCodeArea());

					// se agregan los subprogramas en un Map. codigo,nombre.
					Iterator<SubprogramaVO> it = subprogramas.iterator();
					Map<Long, String> map = new HashMap<Long, String>();
					while (it.hasNext()) {
						SubprogramaVO subprogramaVO = (SubprogramaVO) it.next();
						map.put(subprogramaVO.getCode(),
								subprogramaVO.getNombre());
					}

					// Se obtiene la representacion JSON del map.
					String json = JSONObject.toJSONString(map);
					formBean.setSubprogramas(subprogramas);

					// se asigna el contentType tipo JSON para cargar la lista
					// de subprogramas en el JSP usando ajax.
					response.setContentType("application/json;charset=UTF-8");

					// se escribe en el response el json que representa el map
					// de los subprogramas.
					response.getWriter().write(json);

					// retornar null para no redireccionar.
					return null;
				} catch (NumberFormatException e) {
					return null;
				} catch (Exception e) {
					e.printStackTrace();
					logger.error(e);
				}
			}
		}

		// Filtros.
		// Operacion seleccionar un atributo (parametro)
		if (formBean.getOperacion()
				.equalsIgnoreCase(Utility.OP_SELECT_ATRIBUTO)) {
			if (!formBean.getCodeAtributo().equals("")) {
				try {
					CondicionConsultaUtilVO condicionConsultaUtilVO = filtrosReportesUtil
							.obtainCondicionConsulta(formBean.getCodeAtributo());
					// Collection CondicionConsultaVO
					Collection<CondicionConsultaVO> operadores = condicionConsultaUtilVO
							.getOperadores();
					Collection<CondicionConsultaVO> valores1 = condicionConsultaUtilVO
							.getValores1();

					formBean.setOperadores(operadores);
					if (valores1 != null && !valores1.isEmpty()) {
						formBean.setValores1(valores1);
					} else {
						formBean.setValores1(null);
					}

					formBean.setValores2(null);
					formBean.setTipoCampo(condicionConsultaUtilVO
							.getTipoCampo());
					logger.info("tipocampo " + formBean.getTipoCampo());

					/*
					 * Iterator it = operadores.iterator(); while (it.hasNext())
					 * { CondicionConsultaVO condicionConsultaVO =
					 * (CondicionConsultaVO) it .next();
					 * operadoresMap.put(condicionConsultaVO.getCodfiltro(),
					 * condicionConsultaVO.getFiltro()); } it =
					 * valores1.iterator(); while (it.hasNext()) {
					 * CondicionConsultaVO condicionConsultaVO =
					 * (CondicionConsultaVO) it .next();
					 * valores1Map.put(condicionConsultaVO.getCodfiltro(),
					 * condicionConsultaVO.getFiltro()); }
					 */
					// Crear un String JSON para cada lista.
					/*
					 * String jsonOperadores =
					 * JSONObject.toJSONString(operadoresMap); String
					 * jsonValores1 = JSONObject.toJSONString(valores1Map);
					 * 
					 * // se hace un array con ambos JSON, para llenar ambas
					 * listas. String json = "[" + jsonOperadores + "," +
					 * jsonValores1 + "]";
					 * 
					 * System.out.println(json);
					 */

					// se asigna el contentType tipo JSON para cargar la lista
					// de subprogramas en el JSP usando ajax.
					// response.setContentType("application/json;charset=UTF-8");

					// se escribe en el response el json que representa el map
					// de los subprogramas.
					// response.getWriter().write(json);
				} catch (Exception e) {
					logger.error(e);
				}
			}
		}

		// operacion agregar filtro
		if (formBean.getOperacion().equalsIgnoreCase(Utility.OP_ADD_FILTRO)) {
			CondicionConsultaVO condicionConsultaVO = new CondicionConsultaVO();
			condicionConsultaVO.setCodigo(formBean.getCodeAtributo());
			condicionConsultaVO.setCodcampo(formBean.getCodeAtributo());
			condicionConsultaVO.setCampo(formBean.getEtiquetaAtributo());
			condicionConsultaVO.setTipoCampo(formBean.getTipoCampo());
			condicionConsultaVO.setCodFiltro(formBean.getCodeOperador());
			condicionConsultaVO.setFiltro(formBean.getEtiquetaOperador());
			if (formBean.getEtiquetaValor1() != null
					&& !formBean.getEtiquetaValor1().equals("")) {
				condicionConsultaVO.setEtiquetaValor(formBean
						.getEtiquetaValor1());
				condicionConsultaVO.setValor(formBean.getValor1());
			} else {
				condicionConsultaVO.setEtiquetaValor(formBean.getValor1());
				condicionConsultaVO.setValor(formBean.getValor1());
			}
			// System.out.println(condicionConsultaVO.getEtiquetaValor());
			condicionConsultaVO.setEtiquetaValor2(formBean.getValor2());
			condicionConsultaVO.setValor2(formBean.getValor2());

			// formBean.getFiltros().add(condicionConsultaVO);

			formBean.setCodeAtributo("");

			Collection<CondicionConsultaVO> filters = (Collection<CondicionConsultaVO>) session
					.getAttribute("filtrosRepTotComuna");
			if (filters != null) {
				filters.add(condicionConsultaVO);
				formBean.setFiltros(filters);
			} else {
				Collection<CondicionConsultaVO> col = new ArrayList<CondicionConsultaVO>();
				col.add(condicionConsultaVO);
				// session.setAttribute("filtrosRepTotComuna", col);
				formBean.setFiltros(col);
			}
			session.setAttribute("filtrosRepTotComuna", formBean.getFiltros());
			formBean.setValor1("");

		}
		// operacion eliminar filtro
		if (formBean.getOperacion().equalsIgnoreCase(Utility.OP_DELETE_FILTRO)) {
			Collection<CondicionConsultaVO> filtros = formBean.getFiltros();

			int index = formBean.getIndexFilter();
			int count = 1;
			Iterator<CondicionConsultaVO> it = filtros.iterator();
			while (it.hasNext()) {
				it.next();
				if (index == count) {
					it.remove();
					break;
				} else {
					count++;
				}
			}
		}

		if (formBean.getOperacion()
				.equalsIgnoreCase(Utility.OP_GENERAR_REPORTE)) {

			Collection<ReportComunaVO> cobeneficio = null;
			try {
				ReporteTotalComunaVO objDetBeneVO = new ReporteTotalComunaVO();

				if (formBean.getCodeZona() != null
						&& !formBean.getCodeZona().equals("")) {
					objDetBeneVO.setCodeZona(new Long((String) formBean
							.getCodeZona()));
				}
				if (formBean.getCodeComuna() != null
						&& !formBean.getCodeComuna().equals("")) {
					objDetBeneVO.setCodeComuna(new Long((String) formBean
							.getCodeComuna()));
				}
				if (formBean.getCodePrograma() != null
						&& !formBean.getCodePrograma().equals("")) {
					objDetBeneVO.setCodePrograma(new Long((String) formBean
							.getCodePrograma()));
				}
				if (formBean.getCodeSubprograma() != null
						&& !formBean.getCodeSubprograma().equals("")) {
					objDetBeneVO.setCodeSubprograma(new Long((String) formBean
							.getCodeSubprograma()));
				}
				if (!formBean.getFechaIni().equals("")) {
					objDetBeneVO.setDesde(formBean.getFechaIni());
				}
				if (!formBean.getFechaFin().equals("")) {
					objDetBeneVO.setHasta(formBean.getFechaFin());
				}
				objDetBeneVO.setTipoReporte(formBean.getTipoReporte());
				// session.setAttribute("Parametros", objDetBeneVO);

				objDetBeneVO = reporteTotalComunaServiceImpl
						.findFilters(objDetBeneVO);
				Collection<CondicionConsultaVO> filtros = formBean.getFiltros();

				cobeneficio = reporteTotalComunaServiceImpl
						.findBeneficiosBeneficiariosComuna(objDetBeneVO,
								filtros);
				if (cobeneficio != null) {
					if (cobeneficio.size() > 0) {
						formBean.setBeneficios(cobeneficio);
						session.setAttribute("beneficiosReporteTotalComuna",
								cobeneficio);
						request.setAttribute("criteriaRepTotComuna",
								objDetBeneVO);
						session.setAttribute("criteriaRepTotComuna",
								objDetBeneVO);
					}
				}
				objDetBeneVO = null;
			} catch (DAOException e) {
				SUBException.logDebugError("", e);
			} catch (Exception e) {
				SUBException.logDebugError("", e);
			}

			return mapping.findForward("ir");

		}
		request.setAttribute("tipoReporte", formBean.getTipoReporte());
		return mapping.findForward("success");
	}

	private Collection<SubprogramaVO> findSubprogramas(UserVO user,
			ReportTotalComunaForm formBean) {
		return subprogramaServiceImpl.findSubprogramaUser(user.getCode(),
				user.getUserGroupName(), new Long(formBean.getCodePrograma()),
				user.getCodeArea());
	}
}